package com.yhb.controller.admin;

import com.yhb.channel.ChannelDispatcher;
import com.yhb.channel.model.TryBindRemitCardException;
import com.yhb.conf.ResultCode;
import com.yhb.controller.form.WithdrawForm;
import com.yhb.controller.vo.ArrayWrapperVo;
import com.yhb.controller.vo.SingleValueWrapVo;
import com.yhb.model.BalanceFlow;
import com.yhb.model.MQMessage;
import com.yhb.model.RapidCheat;
import com.yhb.model.User;
import com.yhb.model.mq.SumUpParam;
import com.yhb.model.mq.TimeRangeParam;
import com.yhb.service.BalanceService;
import com.yhb.service.CardService;
import com.yhb.service.MQService;
import com.yhb.service.UserService;
import com.yhb.yinsheng.UnionPayService;
import lombok.var;
import me.edzh.spring.bootstrap.annotations.CurrentUser;
import me.edzh.spring.bootstrap.annotations.EncryptedRequestBody;
import me.edzh.spring.bootstrap.annotations.NeedAuth;
import me.edzh.spring.bootstrap.controller.BaseController;
import me.edzh.spring.bootstrap.model.Response;
import me.edzh.spring.bootstrap.service.ObjectiveStorageService;
import me.edzh.spring.bootstrap.utils.Constants;
import me.edzh.spring.bootstrap.utils.exception.ServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/admin/balance")

//收益管理
public class AdminBalanceController extends BaseController {
    @Qualifier("ossServiceImpl")
    @Autowired
    private ObjectiveStorageService objectiveStorageService;

    @Autowired
    private BalanceService balanceService;

    @Autowired
    private UserService userService;

    @Autowired
    private UnionPayService unionPayService;

    @Autowired
    private ChannelDispatcher channelDispatcher;

    @Autowired
    private CardService cardService;

    @Qualifier("MQServiceImpl")
    @Autowired
    private MQService mqService;

    @NeedAuth(User.A_ADMIN)
    @GetMapping("/clearAll")
    public Response clearAll() {
        List<String> rootUsers = userService.getAllUserId();
        for (String userId : rootUsers) {
            MQMessage mqMessage = MQMessage.builder()
                    .type(MQMessage.T_CLEAR_USER_RESERVED_BALANCE)
                    .content(SumUpParam.builder()
                            .userId(userId)
                            .build())
                    .build();

            mqService.sendMsg(mqMessage);
        }
        return Response.ok();

    }

    @NeedAuth(User.A_ADMIN)
    @PostMapping("/exportWithdrawList")
    public Response<SingleValueWrapVo<String>> outputWithdrawFlows(@RequestBody TimeRangeParam param) {
        return Response.ok(new SingleValueWrapVo<>(balanceService.withdrawListUrlForRange(param.getStartTime(), param.getEndTime())));
    }

    @NeedAuth(User.A_ADMIN)
    @PostMapping("/reserve/{type}/query")
    public Response<ArrayWrapperVo<BalanceFlow>> outputWithdrawFlows(@RequestBody User u, @PathVariable("type") String type) {
        var user = userService.getUserByMobilePhone(u.getMobile());
        if (RapidCheat.Type.UNION_PAY_CHANNEL.name().equals(type)) {
            var balance = unionPayService.queryBalance(user);
            return Response.ok(new ArrayWrapperVo<>(Arrays.asList(BalanceFlow.builder()
                    .amount(balance)
                    .additionalInfos(RapidCheat.Type.UNION_PAY_CHANNEL.name())
                    .description(new HashMap<String, String>() {{
                        put("channelName", "银联闪付");
                    }})
                    .build())));
        } else {
            if (RapidCheat.Type.COMMON_CHANNEL.name().equals(type)) {
                var balances = channelDispatcher.queryUserBalance(user.getId());
                return Response.ok(new ArrayWrapperVo<>(balances.parallelStream()
                        .filter(b -> b.getBalance().compareTo(BigDecimal.ZERO) > 0)
                        .map(b -> BalanceFlow.builder()
                                .amount(b.getBalance())
                                .additionalInfos(b.getChannelType())
                                .description(new HashMap<String, String>() {{
                                    put("channelName", "通道-" + b.getChannelName() + "余额");
                                }})
                                .build()
                        )
                        .sorted(Comparator.comparing(BalanceFlow::getAmount).reversed())
                        .collect(Collectors.toList())
                ));

            }
        }

        throw new ServiceException(ResultCode.ERROR_PARAMETER_WRONG, "UNSUPPORTED SITUATION");
    }

    @PostMapping("/reserve/{channelId}/withdraw")
    @NeedAuth(User.A_ADMIN)
    public Response withdrawReverseBalance(@RequestBody WithdrawForm withdrawForm, @PathVariable("channelId") String channelId) {
        var user = userService.getUserByMobilePhone(withdrawForm.getMobile());
        if (RapidCheat.Type.UNION_PAY_CHANNEL.name().equals(channelId)) {
            unionPayService.activeWithdrawAllReserveBalance(user, withdrawForm.getCardId(), withdrawForm.getAmount());
        } else {
            if (BigDecimal.valueOf(20).compareTo(withdrawForm.getAmount()) >= 0) {
                throw new ServiceException(ResultCode.ERROR_TOAST_ERR, "提现金额过小");
            }
            try {
                channelDispatcher.tryRemit(channelId,
                        user,
                        cardService.cardWithOwnerCheck(withdrawForm.getCardId(), user.getId()),
                        null,
                        withdrawForm.getAmount().subtract(BigDecimal.valueOf(1.)),
                        BigDecimal.valueOf(1.),
                        Constants.getCurrentRemoteIp(),
                        "0",
                        "",
                        "",
                        "");
            } catch (TryBindRemitCardException ignored) {

            }
        }
        return Response.ok();
    }


}
